using System;
using Holoville.HOTween;
using Photon;
using UnityEngine;

public class ThirdPersonController : Photon.MonoBehaviour
{
	private enum CharacterState
	{
		Idle = 0,
		Walking = 1,
		Trotting = 2,
		Running = 3,
		Jumping = 4,
		SwimmingIdle = 5,
		SwimmingWalk = 6,
		SwimmingRun = 7
	}

	public PlayerMecanimWrapper mecanimWrapper;

	public float walkMaxAnimationSpeed = 0.75f;

	public float trotMaxAnimationSpeed = 1f;

	public float runMaxAnimationSpeed = 1f;

	public float jumpAnimationSpeed = 1.15f;

	public float landAnimationSpeed = 1f;

	public GameObject weaponAnimationObject;

	public GameObject joystick;

	private CharacterController controller;

	[HideInInspector]
	public UIJoystick joyScript;

	private float jetpackAcceleration = 7f;

	public PlayerBehavior pBehavior;

	public JetpackBehavior jetpack;

	public AudioClip jetpackSound;

	public AudioClip[] arrWalkSound;

	public float stamina = 1f;

	public bool isRunning;

	public bool isPlayAnimation = true;

	public bool needPlayAnimDrop;

	public LayerMask collisionLayerForDamageAboutWater;

	public Camera mainCamera;

	private CharacterState pred_CharacterState;

	[SerializeField]
	private float walkSpeed;

	[SerializeField]
	private float trotSpeed = 8f;

	[SerializeField]
	private float runSpeed = 15f;

	[SerializeField]
	private float waterWalkSpeed = 4f;

	[SerializeField]
	private float waterRunSpeed = 8f;

	public float inAirControlAcceleration = 3f;

	public float jumpHeight = 0.5f;

	public float gravity = 20f;

	public float speedSmoothing = 10f;

	public float rotateSpeed = 500f;

	public float trotAfterSeconds = 3f;

	public bool canJump = true;

	private float jumpRepeatTime = 0.05f;

	private float jumpTimeout = 0.15f;

	private float groundedTimeout = 0.25f;

	private float lockCameraTimer;

	public Vector3 moveDirection = Vector3.zero;

	public float verticalSpeed;

	public float moveSpeed;

	private CollisionFlags collisionFlags;

	public bool jumping;

	private bool jumpingReachedApex;

	private bool movingBack;

	public bool isMoving;

	private float walkTimeStart;

	public float lastJumpButtonTime = -10f;

	private float lastJumpTime = -1f;

	public Vector3 inAirVelocity = Vector3.zero;

	private float lastGroundedTime;

	private bool isControllable = true;

	public float downSpeedMove = 1f;

	private float dist;

	[HideInInspector]
	public Vector3 predPos = Vector3.zero;

	[HideInInspector]
	public bool predIsGround = true;

	private float minHighForDamage = 7f;

	private float porogSpeedFly = 50f;

	private float posThenFlyDown;

	private bool propProv;

	private bool isFlyDown;

	private float timeLastPlayWalk;

	private float timeDelayPalyWalk = 0.4f;

	public Vector2 dirSpeedMove = Vector3.zero;

	private Vector3 vectUp = Vector3.zero;

	private bool needLookAtObj;

	private Vector3 dirLookAt = Vector3.zero;

	private Vector3 cashVect = Vector3.zero;

	public float compensateHorizontalTrashold = 0.5f;

	public float WalkSpeed
	{
		get
		{
			return walkSpeed;
		}
		set
		{
			walkSpeed = value;
		}
	}

	public float TrotSpeed
	{
		get
		{
			if ((bool)pBehavior && pBehavior.inWater)
			{
				return WaterWalkSpeed;
			}
			return trotSpeed;
		}
		set
		{
			trotSpeed = value;
		}
	}

	public float RunSpeed
	{
		get
		{
			if ((bool)pBehavior && pBehavior.inWater)
			{
				return WaterRunSpeed;
			}
			return runSpeed;
		}
		set
		{
			runSpeed = value;
		}
	}

	public float WaterWalkSpeed
	{
		get
		{
			return waterWalkSpeed * pBehavior.GetSwimmingMultiplier();
		}
	}

	public float WaterRunSpeed
	{
		get
		{
			return waterRunSpeed;
		}
		set
		{
			waterRunSpeed = value;
		}
	}

	private float JumpHeight
	{
		get
		{
			return jumpHeight * pBehavior.GetJumpMultiplier();
		}
	}

	private bool isMine
	{
		get
		{
			return pBehavior.isMine;
		}
	}

	private void Awake()
	{
		HOTween.Init();
		controller = GetComponent<CharacterController>();
		moveDirection = base.transform.TransformDirection(Vector3.forward);
		timeLastPlayWalk = Time.timeSinceLevelLoad;
	}

	private void Start()
	{
		if (pBehavior == null)
		{
			pBehavior = GetComponent<PlayerBehavior>();
		}
		if (isMine)
		{
			grabControls();
		}
		if (jetpack == null)
		{
			jetpack = base.transform.Find("JetPack").gameObject.GetComponent<JetpackBehavior>();
		}
		if (jetpack != null)
		{
			jetpack.GetComponent<JetpackBehavior>().ValidateFuel();
			jetpack.gameObject.SetActive(false);
		}
		mecanimWrapper = pBehavior.mecanimWrapper;
		predPos = base.gameObject.transform.position;
		mainCamera = Camera.main;
	}

	private void Update()
	{
		if (Input.GetKeyDown(KeyCode.K))
		{
			GameController.instance.playerScript.Kill();
		}
		if (isMine && !pBehavior.inHelic && !pBehavior.onLadder && !GameController.instance.useZipLine)
		{
			if (!predIsGround)
			{
				if (IsGrounded() && !propProv)
				{
					bool flag = false;
					if (isFlyDown)
					{
						isFlyDown = false;
						float num = posThenFlyDown - base.transform.position.y;
						if (minHighForDamage < num && !pBehavior.isDead && !pBehavior.ImmunToDamageFromFalling())
						{
							int num2 = (int)(num - minHighForDamage);
							Ray ray = new Ray(base.transform.position, base.transform.up * -1f);
							RaycastHit hitInfo;
							if (Physics.Raycast(ray, out hitInfo, float.PositiveInfinity, collisionLayerForDamageAboutWater) && hitInfo.transform.tag == "Water")
							{
								flag = true;
							}
							if (flag)
							{
								num2 = (int)((float)num2 * 0.25f);
								pBehavior.DiveUnderWater();
								needPlayAnimDrop = false;
								pBehavior.alreadyDontFly();
							}
							num2 = Mathf.RoundToInt((float)num2 * 10f);
							pBehavior.GetDamage(num2, 2, PlayerBehavior.MyPlayer.viewId);
							predIsGround = true;
						}
					}
					if (!pBehavior.isDead && needPlayAnimDrop)
					{
						needPlayAnimDrop = false;
						if (posThenFlyDown - base.transform.position.y > 7f)
						{
							pBehavior.animDropAfterFlyDown();
						}
						else
						{
							pBehavior.alreadyDontFly();
						}
					}
				}
				else
				{
					dist = predPos.y - base.gameObject.transform.position.y;
					downSpeedMove = 3.6f * dist / Time.deltaTime;
					if (downSpeedMove > 0f && !isFlyDown)
					{
						isFlyDown = true;
						posThenFlyDown = base.transform.position.y;
					}
					if ((downSpeedMove.Equals(0f) || downSpeedMove < 0f) && isFlyDown)
					{
						isFlyDown = false;
					}
					if (downSpeedMove > porogSpeedFly)
					{
						mecanimWrapper.SwitchRoll(true);
						if (settings.offlineMode || !base.photonView.isMine || !needPlayAnimDrop)
						{
						}
						needPlayAnimDrop = true;
					}
				}
			}
			propProv = pBehavior.isDead;
			predPos = base.gameObject.transform.position;
			predIsGround = IsGrounded();
		}
		if (!isMine || pBehavior.damageFromCar)
		{
			return;
		}
		if (!isControllable)
		{
			Input.ResetInputAxes();
		}
		if (pBehavior.isDead && Input.GetButtonDown("Jump"))
		{
			lastJumpButtonTime = Time.time;
		}
		UpdateSmoothedMovementDirection();
		ApplyGravity();
		ApplyJumping();
		if (!pBehavior.canMove)
		{
			moveDirection = Vector3.Lerp(moveDirection, Vector3.zero, Time.deltaTime * 5f);
		}
		vectUp.y = verticalSpeed;
		Vector3 motion = moveDirection * moveSpeed + vectUp + inAirVelocity;
		motion *= Time.deltaTime;
		if (controller.enabled)
		{
			collisionFlags = controller.Move(motion);
		}
		if (needLookAtObj)
		{
			base.transform.eulerAngles = new Vector3(0f, GameController.instance.tpsCamera.gameObject.transform.eulerAngles.y, 0f);
			needLookAtObj = false;
		}
		else if (isMine && isMoving && !pBehavior.FPSCameraEnabled)
		{
			dirLookAt = GameController.instance.tpsCamera.transform.eulerAngles;
			dirLookAt.x = 0f;
			dirLookAt.z = 0f;
			base.transform.eulerAngles = dirLookAt;
		}
		if (IsGrounded())
		{
			lastGroundedTime = Time.time;
			inAirVelocity = Vector3.zero;
			if (jumping)
			{
				jumping = false;
			}
		}
	}

	private void CalculateDirMove()
	{
		float num = Vector3.Angle(moveDirection, base.transform.forward);
		float num2 = Vector3.Angle(moveDirection, base.transform.right);
		dirSpeedMove.y = (0f - num + 90f) / 90f * moveSpeed;
		dirSpeedMove.x = (0f - num2 + 90f) / 90f * moveSpeed;
	}

	public void LookAtTarget()
	{
		if (settings.rotatePlayerOnTarget)
		{
			if (BCWDebug.isDebugBuild)
			{
			}
			needLookAtObj = true;
			cashVect.y = GameController.instance.tpsCamera.gameObject.transform.eulerAngles.y;
			base.transform.eulerAngles = cashVect;
		}
	}

	private void UpdateSmoothedMovementDirection()
	{
		Transform transform = mainCamera.transform;
		bool flag = IsGrounded();
		Vector3 vector = ((!pBehavior.FPSCameraEnabled) ? transform.TransformDirection(Vector3.forward) : base.transform.forward);
		vector.y = 0f;
		vector = vector.normalized;
		Vector3 vector2 = new Vector3(vector.z, 0f, 0f - vector.x);
		float num = 0f;
		float num2 = 0f;
		if (joyScript != null && !GameController.instance.playerScript.isDead)
		{
			if (GameController.instance.useLestncu)
			{
				num = 0f;
				num2 = 0f;
				lastGroundedTime = Time.time;
				inAirVelocity = Vector3.zero;
				moveSpeed = 0f;
			}
			else
			{
				num2 = joyScript.position.x;
				num = joyScript.position.y;
			}
		}
		movingBack = num < 0f;
		bool flag2 = isMoving;
		isMoving = (double)Mathf.Abs(num2) > 0.1 || (double)Mathf.Abs(num) > 0.1;
		Vector3 vector3 = num2 * vector2 + num * vector;
		if (flag)
		{
			lockCameraTimer += Time.deltaTime;
			if (isMoving != flag2)
			{
				lockCameraTimer = 0f;
			}
			if (vector3 != Vector3.zero && pBehavior.canMove)
			{
				if ((double)moveSpeed < (double)WalkSpeed * 0.9 && flag)
				{
					moveDirection = vector3.normalized;
				}
				else
				{
					moveDirection = Vector3.RotateTowards(moveDirection, vector3, rotateSpeed * ((float)Math.PI / 180f) * Time.deltaTime, 1000f);
					moveDirection = moveDirection.normalized;
				}
			}
			float t = speedSmoothing * Time.deltaTime;
			float num3 = Mathf.Min(vector3.magnitude, 1f);
			if (!isRunning && stamina < 1f)
			{
				stamina += 0.15f * Time.deltaTime;
			}
			if (0 == 0 && !Input.GetKey(KeyCode.LeftShift) && !Input.GetKey(KeyCode.RightShift) && (!(stamina > 0f) || !isRunning || !isMoving))
			{
				num3 = ((!(Time.time - trotAfterSeconds > walkTimeStart)) ? (num3 * WalkSpeed) : (num3 * TrotSpeed));
			}
			else
			{
				stamina -= 0.23f * Time.deltaTime;
				num3 *= RunSpeed;
			}
			if (pBehavior.weaponManager.currentWeaponScript != null)
			{
				moveSpeed = moveSpeed * ((!pBehavior.inWater) ? Mathf.Clamp((float)pBehavior.weaponManager.currentWeaponScript.Mobility * pBehavior.speedModifier, 0f, 100f) : 100f) / 100f;
				moveSpeed = Mathf.Lerp(moveSpeed, num3, t);
				if (num3 == 0f)
				{
					moveSpeed = 0f;
				}
				if ((double)moveSpeed < (double)WalkSpeed * 0.3)
				{
					walkTimeStart = Time.time;
				}
			}
		}
		else if (isMoving)
		{
			inAirVelocity *= 0.95f;
			inAirVelocity += vector3.normalized * Time.deltaTime * inAirControlAcceleration * ((!jetpack.isFlying) ? 1f : jetpackAcceleration);
			if (jetpack.isFlying)
			{
				moveDirection *= 0.99f;
			}
		}
	}

	public void ResetFlyDown()
	{
		posThenFlyDown = base.transform.position.y;
	}

	private void ApplyJumping()
	{
		if (!pBehavior.canMove || lastJumpTime + jumpRepeatTime > Time.time)
		{
			return;
		}
		if (IsGrounded() && jetpack != null && !jetpack.activated)
		{
			if (canJump && Time.time < lastJumpButtonTime + jumpTimeout)
			{
				if (GameController.instance.playerScript != null)
				{
					GameController.instance.playerScript.PlaySoundJump();
				}
				verticalSpeed = CalculateJumpVerticalSpeed(JumpHeight);
				DidJump();
			}
		}
		else if (jetpack != null && jetpack.activated && jetpack.isFlying && !IsGrounded())
		{
			if (jetpack.isFlying)
			{
				verticalSpeed = CalculateJumpVerticalSpeed(JumpHeight);
				DidJump();
			}
		}
		else if (jetpack != null && jetpack.activated && IsGrounded() && canJump && Time.time < lastJumpButtonTime + jumpTimeout)
		{
			if (GameController.instance.playerScript != null)
			{
				GameController.instance.playerScript.PlaySoundJump();
			}
			verticalSpeed = CalculateJumpVerticalSpeed(JumpHeight);
			DidJump();
		}
	}

	private void ApplyGravity()
	{
		if (isControllable)
		{
			if (jumping && !jumpingReachedApex && (double)verticalSpeed <= 0.0)
			{
				jumpingReachedApex = true;
			}
			if (IsGrounded())
			{
				verticalSpeed = 0f;
			}
			else
			{
				verticalSpeed -= gravity * Time.deltaTime;
			}
		}
	}

	private float CalculateJumpVerticalSpeed(float targetJumpHeight)
	{
		return Mathf.Sqrt(2f * targetJumpHeight * gravity);
	}

	public void DidJump()
	{
		jumping = true;
		jumpingReachedApex = false;
		lastJumpTime = Time.time;
		lastJumpButtonTime = -10f;
		mecanimWrapper.Jump();
	}

	private void PlaySoundWalk()
	{
		if (VolumeController.IsSoundEnable && arrWalkSound != null && Time.timeSinceLevelLoad - timeLastPlayWalk > timeDelayPalyWalk)
		{
			timeLastPlayWalk = Time.timeSinceLevelLoad;
			AudioClip audioClip = arrWalkSound[UnityEngine.Random.Range(0, arrWalkSound.Length)];
			if (audioClip != null)
			{
				AudioSource.PlayClipAtPoint(audioClip, base.transform.position, UnityEngine.Random.Range(0.3f, 1f));
			}
		}
	}

	private void grabControls()
	{
		if (isMine)
		{
			joyScript = WalkWindow.instance.joystickWalk;
		}
	}

	public float GetSpeed()
	{
		return moveSpeed;
	}

	public bool IsJumping()
	{
		return jumping;
	}

	public bool IsGrounded()
	{
		return (collisionFlags & CollisionFlags.Below) != 0;
	}

	public Vector3 GetDirection()
	{
		return moveDirection;
	}

	public bool IsMovingBackwards()
	{
		return movingBack;
	}

	public float GetLockCameraTimer()
	{
		return lockCameraTimer;
	}

	public bool IsMoving()
	{
		return (double)(Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal"))) > 0.1;
	}

	private bool HasJumpReachedApex()
	{
		return jumpingReachedApex;
	}

	public bool IsGroundedWithTimeout()
	{
		return lastGroundedTime + groundedTimeout > Time.time;
	}

	private void Reset()
	{
		base.gameObject.tag = "Player";
	}

	public void SetTargetPoint(Vector3 point, bool isFPSMode = false)
	{
		if (controller == null)
		{
			return;
		}
		if (!isFPSMode)
		{
			Vector2 vector = new Vector2(controller.velocity.x, controller.velocity.z);
			if (vector.sqrMagnitude < 0.05f)
			{
				return;
			}
		}
		Vector3 forward = point - base.transform.position;
		Quaternion quaternion = Quaternion.LookRotation(forward);
		base.transform.rotation = Quaternion.Euler(0f, quaternion.eulerAngles.y, 0f);
	}
}
